﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MVCBugTracker.Models;
using MVCBugTracker.ViewModels;
using System.IO;
using System.Web.Security;
using System.Web.Routing;

namespace MVCBugTracker.Controllers
{
    public class ProjectController : Controller
    {
        public IProjectRepository ProjectRepository { get; set; }
        public IBugRepository BugRepository { get; set; }

        protected override void Initialize(RequestContext requestContext)
        {
            if (ProjectRepository == null) { ProjectRepository = new EFProjectRepository(); }
            if (BugRepository == null) { BugRepository = new EFBugRepository(); }

            base.Initialize(requestContext);
        }
        
        // GET: /Project/
        [Authorize(Roles = "Administrator")]
        public ActionResult Index()
        {
            List<Project> projects = new List<Project>();

            if (User.IsInRole("Administrator"))
                projects = ProjectRepository.GetAllProjects().ToList();
            else
                projects = ProjectRepository.GetMyProjects(User.Identity.Name).ToList();

            return View(projects);
        }

        // GET: /Project/Create
        [Authorize(Roles = "Administrator")]
        public ActionResult Create()
        {
            return View();
        } 

        // POST: /Project/Create
        [HttpPost]
        [Authorize(Roles = "Administrator")]
        public ActionResult Create(Project project)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    project.CreatorName = User.Identity.Name;
                    project.DateCreated = DateTime.Now;
                    project.LastUpdate = DateTime.Now;
                    project.Deleted = false;

                    ProjectRepository.AddProject(project);
                    ProjectRepository.Save();

                    ProjectMember newMember = new ProjectMember()
                    {
                        ProjectID = project.ProjectID,
                        UserName = project.CreatorName
                    };
                    ProjectRepository.AddProjectMember(newMember);
                    ProjectRepository.Save();

                    return RedirectToAction("Index");
                }
                catch
                {
                    return View();
                }
            }
            else
            {
                return View();
            }
        }
        
        // GET: /Project/Edit/5
        [Authorize(Roles = "Administrator")]
        public ActionResult Edit(int id)
        {
            var viewModel = new ProjectEditViewModel();

            viewModel.Project = ProjectRepository.GetProject(id);
            viewModel.ProjectMilestoneViewModel  = new ProjectMilestoneViewModel
            {
                ProjectID = id,
                Milestones = ProjectRepository.GetProjectMilestones(id).ToList()
            };
            //Get Images
            var milestoneImages = from f in new DirectoryInfo(Server.MapPath("~/Content/Images/Milestone")).GetFiles()
                                 select f.Name;
            foreach (string s in milestoneImages)
            {
                viewModel.ProjectMilestoneViewModel.ImagesUrls.Add("~/Content/Images/Milestone/" + s);
            }
            viewModel.ProjectCategoryViewModel = new ProjectCategoryViewModel()
            {
                ProjectID = id,
                Categories = ProjectRepository.GetProjectCategories(id).ToList()
            };
            viewModel.ProjectPriorityViewModel = new ProjectPriorityViewModel()
            {
                ProjectID = id,
                Priorities = ProjectRepository.GetProjectPriorities(id).ToList()
            };
            //Get Images
            var priorityImages = from f in new DirectoryInfo(Server.MapPath("~/Content/Images/Priority")).GetFiles()
                        select f.Name;
            foreach (string s in priorityImages)
            {
                viewModel.ProjectPriorityViewModel.ImagesUrls.Add("~/Content/Images/Priority/" + s);
            }
            viewModel.ProjectStatusViewModel = new ProjectStatusViewModel()
            {
                ProjectID = id,
                Statuses = ProjectRepository.GetProjectStatuses(id).ToList()
            };
            //Get Images
            var statusImages = from f in new DirectoryInfo(Server.MapPath("~/Content/Images/Status")).GetFiles()
                        select f.Name;
            foreach (string s in statusImages)
            {
                viewModel.ProjectStatusViewModel.ImagesUrls.Add("~/Content/Images/Status/" + s);
            }

            viewModel.ProjectCustomFieldViewModel = new ProjectCustomFieldViewModel()
            {
                ProjectID = id,
                CustomFields = ProjectRepository.GetProjectCustomFields(id).ToList()
            };

            viewModel.ProjectMemberViewModel = new ProjectMemberViewModel()
            {
                ProjectID = id,
                Members = ProjectRepository.GetProjectMembers(id).ToList()
            };
            viewModel.ProjectMemberViewModel.AllUsers = (from MembershipUser m in Membership.GetAllUsers()
                                                         orderby m.UserName ascending
                                                         select m.UserName).ToList();



            if (viewModel.Project != null)
                return View(viewModel);
            else
                return RedirectToAction("Index");
        }

        // POST: /Project/Edit/5
        [HttpPost]
        [Authorize(Roles = "Administrator")]
        public ActionResult Edit(int id, FormCollection collection)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    Project project = ProjectRepository.GetProject(id);
                    project.Name = collection["Project.Name"];
                    project.Description = collection["Project.Description"];
                    project.LastUpdate = DateTime.Now;

                    ProjectRepository.Save();

                    return RedirectToAction("Index");
                }
                catch
                {
                    return View();
                }
            }
            else
            {
                return RedirectToAction("Edit", id);
            }
        }

        // GET: /Project/Delete/5
        [Authorize(Roles = "Administrator")]
        public ActionResult Delete(int id)
        {
            Project project = ProjectRepository.GetProject(id);

            if (project == null)
                return View("NotFound");

            return View(project);
        }

        // POST: /Project/Delete/5
        [HttpPost]
        [Authorize(Roles = "Administrator")]
        public ActionResult Delete(int id, FormCollection collection)
        {
            try
            {
                Project project = ProjectRepository.GetProject(id);
                ProjectRepository.DeleteProject(project);
                ProjectRepository.Save();
 
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

        // AJAX: /Project/DeleteMilestone/2
        [HttpPost]
        [Authorize(Roles = "Administrator")]
        public PartialViewResult DeleteMilestone(int id)
        {
            ProjectMilestone milestone = ProjectRepository.GetProjectMilestone(id);
            int projectID = milestone.ProjectID;

            ProjectRepository.DeleteProjectMilestone(milestone);
            ProjectRepository.Save();

            var results = new ProjectMilestoneViewModel
            {
                Message = Server.HtmlEncode(milestone.Name) + " has been removed from the project.",
                ProjectID = projectID,
                Milestones = ProjectRepository.GetProjectMilestones(projectID).ToList()
            };
            //Get Images
            var milestoneImages = from f in new DirectoryInfo(Server.MapPath("~/Content/Images/Milestone")).GetFiles()
                                  select f.Name;
            foreach (string s in milestoneImages)
            {
                results.ImagesUrls.Add("~/Content/Images/Milestone/" + s);
            }
            return PartialView("ProjectMilestones", results);
        }

        // AJAX: /Project/AddMilestone/2
        [HttpPost]
        [Authorize(Roles = "Administrator")]
        public PartialViewResult AddMilestone(int id, FormCollection collection)
        {
            ProjectMilestone milestone = new ProjectMilestone();
            milestone.ProjectID = id;
            milestone.Name = Server.HtmlEncode(collection["milestonename"]);
            milestone.ImageUrl = collection["imageurl"];
            milestone.DateCreated = DateTime.Now;

            ProjectRepository.AddProjectMilestone(milestone);
            ProjectRepository.Save();

            var results = new ProjectMilestoneViewModel
            {
                Message = Server.HtmlEncode(milestone.Name) + " has been added to the project.",
                ProjectID = id,
                Milestones = ProjectRepository.GetProjectMilestones(id).ToList()
            };
            //Get Images
            var milestoneImages = from f in new DirectoryInfo(Server.MapPath("~/Content/Images/Milestone")).GetFiles()
                                  select f.Name;
            foreach (string s in milestoneImages)
            {
                results.ImagesUrls.Add("~/Content/Images/Milestone/" + s);
            }
            return PartialView("ProjectMilestones", results);
        }

        // AJAX: /Project/DeleteCategory/2
        [HttpPost]
        [Authorize(Roles = "Administrator")]
        public PartialViewResult DeleteCategory(int id)
        {
            ProjectCategory category = ProjectRepository.GetProjectCategory(id);
            int projectID = category.ProjectID;

            //null any bugs with this category
            List<Bug> bugs = BugRepository.GetBugsByCategory(projectID, id).ToList();
            foreach (Bug b in bugs)
            {
                //b.CategoryID = 0;
            }


            ProjectRepository.DeleteProjectCategory(category);
            ProjectRepository.Save();

            var results = new ProjectCategoryViewModel
            {
                Message = Server.HtmlEncode(category.Name) + " has been removed from the project.",
                ProjectID = projectID,
                Categories = ProjectRepository.GetProjectCategories(projectID).ToList()
            };
            return PartialView("ProjectCategories", results);
        }

        // AJAX: /Project/AddCategory/2
        [HttpPost]
        [Authorize(Roles = "Administrator")]
        public PartialViewResult AddCategory(int id, FormCollection collection)
        {
            ProjectCategory category = new ProjectCategory();
            category.ProjectID = id;
            category.Name = Server.HtmlEncode(collection["categoryname"]);
            category.DateCreated = DateTime.Now;

            ProjectRepository.AddProjectCategory(category);
            ProjectRepository.Save();

            var results = new ProjectCategoryViewModel
            {
                Message = Server.HtmlEncode(category.Name) + " has been added to the project.",
                ProjectID = id,
                Categories = ProjectRepository.GetProjectCategories(id).ToList()
            };
            return PartialView("ProjectCategories", results);
        }

        // AJAX: /Project/DeletePriority/2
        [HttpPost]
        [Authorize(Roles = "Administrator")]
        public PartialViewResult DeletePriority(int id)
        {
            ProjectPriority priority = ProjectRepository.GetProjectPriority(id);
            int projectID = priority.ProjectID;

            ProjectRepository.DeleteProjectPriority(priority);
            ProjectRepository.Save();

            var results = new ProjectPriorityViewModel
            {
                Message = Server.HtmlEncode(priority.Name) + " has been removed from the project.",
                ProjectID = projectID,
                Priorities = ProjectRepository.GetProjectPriorities(projectID).ToList()
            };
            //Get Images
            var files = from f in new DirectoryInfo(Server.MapPath("~/Content/Images/Priority")).GetFiles()
                        select f.Name;
            foreach (string s in files)
            {
                results.ImagesUrls.Add("~/Content/Images/Priority/" + s);
            }
            return PartialView("ProjectPriorities", results);
        }

        // AJAX: /Project/AddPriority/2
        [HttpPost]
        [Authorize(Roles = "Administrator")]
        public PartialViewResult AddPriority(int id, FormCollection collection)
        {
            ProjectPriority priority = new ProjectPriority();
            priority.ProjectID = id;
            priority.Name = Server.HtmlEncode(collection["priorityname"]);
            priority.ImageUrl = collection["imageurl"];
            priority.DateCreated = DateTime.Now;

            ProjectRepository.AddProjectPriority(priority);
            ProjectRepository.Save();

            var results = new ProjectPriorityViewModel
            {
                Message = Server.HtmlEncode(priority.Name) + " has been added to the project.",
                ProjectID = id,
                Priorities = ProjectRepository.GetProjectPriorities(id).ToList()
            };
            //Get Images
            var files = from f in new DirectoryInfo(Server.MapPath("~/Content/Images/Priority")).GetFiles()
                        select f.Name;
            foreach (string s in files)
            {
                results.ImagesUrls.Add("~/Content/Images/Priority/" + s);
            }

            return PartialView("ProjectPriorities", results);
        }

        // AJAX: /Project/DeleteStatus/2
        [HttpPost]
        [Authorize(Roles = "Administrator")]
        public PartialViewResult DeleteStatus(int id)
        {
            ProjectStatus status = ProjectRepository.GetProjectStatus(id);
            int projectID = status.ProjectID;

            ProjectRepository.DeleteProjectStatus(status);
            ProjectRepository.Save();

            var results = new ProjectStatusViewModel
            {
                Message = Server.HtmlEncode(status.Name) + " has been removed from the project.",
                ProjectID = projectID,
                Statuses = ProjectRepository.GetProjectStatuses(projectID).ToList()
            };
            //Get Images
            var files = from f in new DirectoryInfo(Server.MapPath("~/Content/Images/Status")).GetFiles()
                        select f.Name;
            foreach (string s in files)
            {
                results.ImagesUrls.Add("~/Content/Images/Status/" + s);
            }
            return PartialView("ProjectStatuses", results);
        }

        // AJAX: /Project/AddStatus/2
        [HttpPost]
        [Authorize(Roles = "Administrator")]
        public PartialViewResult AddStatus(int id, FormCollection collection)
        {
            ProjectStatus status = new ProjectStatus();
            status.ProjectID = id;
            status.Name = Server.HtmlEncode(collection["statusname"]);
            status.ImageUrl = collection["imageurl"];
            status.DateCreated = DateTime.Now;

            ProjectRepository.AddProjectStatus(status);
            ProjectRepository.Save();

            var results = new ProjectStatusViewModel
            {
                Message = Server.HtmlEncode(status.Name) + " has been added to the project.",
                ProjectID = id,
                Statuses = ProjectRepository.GetProjectStatuses(id).ToList()
            };
            //Get Images
            var files = from f in new DirectoryInfo(Server.MapPath("~/Content/Images/Status")).GetFiles()
                        select f.Name;
            foreach (string s in files)
            {
                results.ImagesUrls.Add("~/Content/Images/Status/" + s);
            }
            return PartialView("ProjectStatuses", results);
        }

        // AJAX: /Project/DeleteCustomField/2
        [HttpPost]
        [Authorize(Roles = "Administrator")]
        public PartialViewResult DeleteCustomField(int id)
        {
            ProjectCustomField customField = ProjectRepository.GetProjectCustomField(id);
            ProjectRepository.DeleteProjectCustomField(customField);
            ProjectRepository.Save();

            var results = new ProjectCustomFieldViewModel
            {
                Message = Server.HtmlEncode(customField.Name) + " has been added to the project.",
                ProjectID = customField.ProjectID,
                CustomFields = ProjectRepository.GetProjectCustomFields(customField.ProjectID).ToList()
            };
            return PartialView("ProjectCustomFields", results);
        }

        // AJAX: /Project/AddCustomField/2
        [HttpPost]
        [Authorize(Roles = "Administrator")]
        public PartialViewResult AddCustomField(int id, FormCollection collection)
        {
            ProjectCustomField customField = new ProjectCustomField();
            customField.ProjectID = id;
            customField.Name = Server.HtmlEncode(collection["fieldname"]);
            customField.Required = bool.Parse(collection["required"] ?? "false");
            customField.DataType = int.Parse(collection["datatype"]);
            customField.Deleted = false;

            ProjectRepository.AddProjectCustomField(customField);
            ProjectRepository.Save();

            var results = new ProjectCustomFieldViewModel
            {
                Message = Server.HtmlEncode(customField.Name) + " has been added to the project.",
                ProjectID = id,
                CustomFields = ProjectRepository.GetProjectCustomFields(id).ToList()
            };

            return PartialView("ProjectCustomFields", results);
        }

        // AJAX: /Project/EditCustomField/2
        [HttpPost]
        [Authorize(Roles = "Administrator")]
        public PartialViewResult EditCustomField(int id, FormCollection collection)
        {
            ProjectCustomField customField = ProjectRepository.GetProjectCustomField(id);
            customField.Required = bool.Parse(collection["required"] ?? "false");
            ProjectRepository.Save();

            var results = new ProjectCustomFieldViewModel
            {
                Message = Server.HtmlEncode(customField.Name) + " has been modified.",
                ProjectID = customField.ProjectID,
                CustomFields = ProjectRepository.GetProjectCustomFields(customField.ProjectID).ToList()
            };
            return PartialView("ProjectCustomFields", results);
        }

        // AJAX: /Project/UpdateMembers/2
        [HttpPost]
        [Authorize(Roles = "Administrator")]
        public PartialViewResult UpdateMembers(int id, FormCollection collection)
        {
            if (collection["add"] != null)
            {
                if (collection["nonmembers"] != null)
                {
                    List<string> users = collection["nonmembers"].Split(',').ToList();
                    foreach (string user in users)
                    {
                        ProjectMember newMember = new ProjectMember()
                        {
                            ProjectID = id,
                            UserName = user
                        };
                        ProjectRepository.AddProjectMember(newMember);
                    }
                    ProjectRepository.Save();
                }
            }
            else
            {
                if (collection["members"] != null)
                {
                    List<string> users = collection["members"].Split(',').ToList();
                    Project project = ProjectRepository.GetProject(id);
                    foreach (string user in users)
                    {
                        ProjectMember member = ProjectRepository.GetProjectMember(id, user);
                        //creator must be a member (for now)
                        if (member != null && member.UserName != project.CreatorName)
                            ProjectRepository.DeleteProjectMember(member);
                    }
                    ProjectRepository.Save();
                }
            }

            var results = new ProjectMemberViewModel()
            {
                ProjectID = id,
                Members = ProjectRepository.GetProjectMembers(id).ToList()
            };
            results.AllUsers = (from MembershipUser m in Membership.GetAllUsers()
                                                         orderby m.UserName ascending
                                                         select m.UserName).ToList();

            return PartialView("ProjectMembers", results);
        }

        // AJAX: /Project/GetMilestoneURL/2
        [Authorize]
        public JsonResult GetMilestoneURL(int id)
        {
            string url = ProjectRepository.GetProjectMilestone(id).ImageUrl;
            return Json(Url.Content(url));
        }

        // AJAX: /Project/GetPriorityURL/2
        [Authorize]
        public JsonResult GetPriorityURL(int id)
        {
            string url = ProjectRepository.GetProjectPriority(id).ImageUrl;
            return Json(Url.Content(url));
        }

        // AJAX: /Project/GetStatusURL/2
        [Authorize]
        public JsonResult GetStatusURL(int id)
        {
            string url = ProjectRepository.GetProjectStatus(id).ImageUrl;
            return Json(Url.Content(url));
        }

    }
}
